package fileDemo;

import org.junit.Test;

import java.io.*;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;

/**
 * @author Ajie
 * @date 2022/7/21
 * @function oom webserver
 * @see RandomAccessFileDemo
 * @see oomxmind
 * <p>
 * ByteBuffer   速度对比：结论：测试没啥。大的区别。速度。  只读、读写。已测试。190MB 3GB 大小 2023-11-28 16:58:47
 * <p>
 * heapByteBuffer
 * <p>
 * directByteBuffer
 * <p>
 * MappedByteBuffer
 */
public class ByteBufferDemo {
    public static void main(String[] args) throws Exception{
        //200MB 的文件差不多。
        //3G 的文件也差不多3s左右。
//        speedJustReadByte();
//        speedJustReadByteBuffer();

        long start = System.currentTimeMillis();
        copyFileTraditionalIO(tempSourceFile,"/Users/macpro/Downloads/temp.mkv");//3个 G 18481
        long tra = System.currentTimeMillis();
        System.out.println("ByteBufferDemo:main:copyFiledur:"+(tra-start));

        copyFileByteBufferNIO(tempSourceFile,"/Users/macpro/Downloads/temp2.mkv");//3个 G 17224
        long nio = System.currentTimeMillis();
        System.out.println("ByteBufferDemo:main:copy NIO:"+(nio-tra));


    }

    public static void webserverTest() {
        RandomAccessFile randomAccessFile = null;
        try {
            randomAccessFile = new RandomAccessFile("./text.txt", "rw");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        try {
            //method 1 read some byte from file

            ByteBuffer heapByteBuffer = ByteBuffer.allocate(1024);//HeapByteBuffer
            byte[] someInputBytes = {1, 2, 3, 4};//eg: byte[] = new ByteArrayOutputStream().toByteArray();
            ByteBuffer bheapByteBuffer2 = ByteBuffer.wrap(someInputBytes, 0, someInputBytes.length);

            //method 2  //DirectByteBuffer
            ByteBuffer directByteBuffer = ByteBuffer.allocateDirect(4096);
            randomAccessFile.seek(0);
            int read = randomAccessFile.getChannel().read(directByteBuffer);
            System.out.println("ByteBufferDemo:main:read len:" + read);


            //method 3 MappedByteBuffer
            randomAccessFile.seek(0);
            MappedByteBuffer map = randomAccessFile.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, randomAccessFile.length());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

//    private static final String tempSourceFile = "/Users/macpro/Downloads/douyin-v3.0.1-darwin-universal-wid-8HAyPEbB3V2.dmg";
    private static final String tempSourceFile = "/Users/macpro/Movies/200.冰雪奇缘1英语.mkv";


    //传统的读写。
    public static void speedJustReadByte() {
        long start = System.currentTimeMillis();
        FileInputStream fis = null;
        try {
            fis = new FileInputStream(tempSourceFile);
            byte[] buffer = new byte[1024]; // 定义一个字节数组作为缓冲区
            int len;
            while ((len = fis.read(buffer)) != -1) {
                // 处理读取的数据
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        long dur = System.currentTimeMillis() - start;
        System.out.println("ByteBufferDemo:speedJustReadByte:传统读写："+dur);

    }
    //bytebuffer NIO 读取 耗时
    public static void speedJustReadByteBuffer() {
        long start = System.currentTimeMillis();
        FileInputStream fis = null;
        FileChannel channel = null;
        try {
            fis = new FileInputStream(tempSourceFile);
            channel = fis.getChannel();
            ByteBuffer buffer = ByteBuffer.allocate(1024); // 创建ByteBuffer
            while (channel.read(buffer) != -1) {
                buffer.flip(); // 切换为读模式
                // 处理读取的数据
                buffer.clear(); // 清空缓冲区，准备下一次读取
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (channel != null) {
                try {
                    channel.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        long dur = System.currentTimeMillis() - start;
        System.out.println("ByteBufferDemo:speedJustReadByte:bytebuffer NIO 耗时："+dur);
    }


    //速度对比：结论：测试没啥。大的区别。速度。
    public static void copyFileTraditionalIO(String sourceFile, String destFile) throws IOException {
        FileInputStream fis = null;
        FileOutputStream fos = null;

        try {
            fis = new FileInputStream(sourceFile);
            fos = new FileOutputStream(destFile);
            byte[] buffer = new byte[1024];
            int length;

            while ((length = fis.read(buffer)) > 0) {
                fos.write(buffer, 0, length);
            }
        } finally {
            if (fis != null) {
                fis.close();
            }
            if (fos != null) {
                fos.close();
            }
        }
    }
    public static void copyFileByteBufferNIO(String sourceFile, String destFile) throws IOException {
        FileInputStream fis = null;
        FileOutputStream fos = null;
        FileChannel inputChannel = null;
        FileChannel outputChannel = null;

        try {
            fis = new FileInputStream(sourceFile);
            fos = new FileOutputStream(destFile);
            inputChannel = fis.getChannel();
            outputChannel = fos.getChannel();
            ByteBuffer buffer = ByteBuffer.allocate(1024);

            while (inputChannel.read(buffer) != -1) {
                buffer.flip(); // 切换到读模式
                outputChannel.write(buffer);
                buffer.clear(); // 清空缓冲区，准备下次写入
            }
        } finally {
            if (inputChannel != null) {
                inputChannel.close();
            }
            if (outputChannel != null) {
                outputChannel.close();
            }
            if (fis != null) {
                fis.close();
            }
            if (fos != null) {
                fos.close();
            }
        }
    }


}
